/* hal_clock.c */
#include "hal_clock.h"

void CLOCK_GetCurrentPlatformClockConfig(CLOCK_PlatformClockConfig_T *config)
{
    config->MainClockSourceSel = (CLOCK_RootClockSourceSel_T)((SCG->CSR & SCG_CSR_SCS_MASK)>>SCG_CSR_SCS_SHIFT);
    config->CoreSystemClockDiv = (SCG->CSR & SCG_CSR_DIVCORE_MASK)>>SCG_CSR_DIVCORE_SHIFT;
    config->BusClockDiv = (SCG->CSR & SCG_CSR_DIVBUS_MASK)>>SCG_CSR_DIVBUS_SHIFT;
    config->SlowClockDiv = (SCG->CSR & SCG_CSR_DIVSLOW_MASK)>>SCG_CSR_DIVSLOW_SHIFT;
}

void CLOCK_SetPlatformClockConfigForPowerRUN(CLOCK_PlatformClockConfig_T *config)
{
    SCG->RCCR = SCG_RCCR_SCS(config->MainClockSourceSel)
              | SCG_RCCR_DIVCORE(config->CoreSystemClockDiv)
              | SCG_RCCR_DIVBUS(config->BusClockDiv)
              | SCG_RCCR_DIVSLOW(config->SlowClockDiv);
}

void CLOCK_SetPlatformClockConfigForPowerVLPR(CLOCK_PlatformClockConfig_T *config)
{
    SCG->VCCR = SCG_VCCR_SCS(config->MainClockSourceSel)
              | SCG_VCCR_DIVCORE(config->CoreSystemClockDiv)
              | SCG_VCCR_DIVBUS(config->BusClockDiv)
              | SCG_VCCR_DIVSLOW(config->SlowClockDiv);
}

void CLOCK_SetPlatformClockConfigForPowerHSRUN(CLOCK_PlatformClockConfig_T *config)
{
    SCG->HCCR = SCG_HCCR_SCS(config->MainClockSourceSel)
              | SCG_HCCR_DIVCORE(config->CoreSystemClockDiv)
              | SCG_HCCR_DIVBUS(config->BusClockDiv)
              | SCG_HCCR_DIVSLOW(config->SlowClockDiv);
}

void CLOCK_SetCLKOUTOutputSel(CLOCK_RootClockSourceSel_T selection)
{
    SCG->CLKOUTCNFG = SCG_CLKOUTCNFG_CLKOUTSEL(selection);
}

void CLOCK_ConfigSystemOSC(CLOCK_SystemOSCConfig_T *config)
{
    if (config != NULL)
    {
        SCG->SOSCCFG = SCG_SOSCCFG_RANGE(config->RangeSel)
                     | SCG_SOSCCFG_HGO(config->PowerModeSel)
                     | SCG_SOSCCFG_EREFS(config->XtalMode)
                     ;

        SCG->SOSCCSR = SCG_SOSCCSR_SOSCERR_MASK  /* Clear the error flag. */
                     | SCG_SOSCCSR_SOSCCMRE_MASK /* Reset the SoC once error. */
                     | (config->EnabledInVLPxModes ? SCG_SOSCCSR_SOSCLPEN_MASK : 0U)
                     | (config->EnabledInSTOPModes ? SCG_SOSCCSR_SOSCSTEN_MASK : 0U)
                     | SCG_SOSCCSR_SOSCEN_MASK;
        /* Wait while the clock is available. */
        while (SCG_SOSCCSR_SOSCVLD_MASK != (SCG->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK) )
        {}
    }
    else /* Disable the System OSC and clear all the settings. */
    {
        SCG->SOSCCSR = SCG_SOSCCSR_SOSCERR_MASK  /* Clear the error flag. */
                     | SCG_SOSCCSR_SOSCCMRE_MASK /* Reset the SoC once error. */
                     ;
    }
}

/* Change the async dividers only when the father clock is disabled. */
void CLOCK_SetSystemOSCAsyncClockDiv(uint32_t div1, uint32_t div2)
{
    SCG->SOSCDIV = SCG_SOSCDIV_SOSCDIV1(div1)
                 | SCG_SOSCDIV_SOSCDIV1(div2);
}

/* Root clock source - Slow IRC (SIRC). */

/* Root clock source - Fast IRC (FIRC). */
void CLOCK_ConfigFastIRC(CLOCK_FastIRCConfig_T *config)
{
    if (NULL == config) /* Disable the Fast IRC clock generator. */
    {
        SCG->FIRCCSR = 0U;
    }
    else
    {
        SCG->FIRCCFG = SCG_FIRCCFG_RANGE(config->ClockRange);
        SCG->FIRCDIV = SCG_FIRCDIV_FIRCDIV1(config->AsyncClkOutputDiv1)
                     | SCG_FIRCDIV_FIRCDIV2(config->AsyncClkOutputDiv2);
        SCG->FIRCCSR = SCG_FIRCCSR_FIRCERR_MASK /* Clear the error flag */
                     | SCG_FIRCCSR_FIRCEN_MASK
                     | ((config->enClkOnStopMode)?SCG_FIRCCSR_FIRCERR_MASK:0U)
                     | ((config->enClkOnVLPxMode)?SCG_FIRCCSR_FIRCLPEN_MASK:0U)
                     ;

        while (SCG_FIRCCSR_FIRCVLD_MASK != (SCG_FIRCCSR_FIRCVLD_MASK & SCG->FIRCCSR))
        {}
    }
}

/* Root clock source - System PLL (SPLL). */

/* EOF */
